package controllers

import (
	"crypto/sha1"
	"encoding/xml"
	"fmt"
	"git.tmuyu.com.cn/beego/models"
	"git.tmuyu.com.cn/beego/service"
	"git.tmuyu.com.cn/beego/util"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"io"
	"io/ioutil"
	"sort"
	"strings"
)

type WxConnectController struct {
	beego.Controller
}

const Token = "jcdpy8m2v9"

func (c *WxConnectController) Get() {
	//微信接入验证 这是首次对接微信 填写url后 微信服务器会发一个请求过来
	//c.Ctx.Request.URL-------
	//http://iii.tmuyu.com.cn/wx_connect?signature=038d75ed5485b9881a01b3b93e85f9fff28ea739&echostr=5756456183388806654&timestamp=1476173150&nonce=1093541731
	//http://127.0.0.1:80/wx_connect?signature=038d75ed5485b9881a01b3b93e85f9fff28ea739&echostr=5756456183388806654&timestamp=1476173150&nonce=1093541731
	//开发者提交信息(包括URL、Token)后，微信服务器将发送Http Get请求到填写的URL上，
	//GET请求携带四个参数：signature、timestamp、nonce和echostr。公众号服务程序应该按如下要求进行接入验证
	timestamp := c.GetString("timestamp")
	signatureIn := c.GetString("signature")
	nonce := c.GetString("nonce")
	echo := c.GetString("echostr")
	signatureGen := makeSignature(timestamp, nonce)
	//将加密后获得的字符串与signature对比，如果一致，说明该请求来源于微信
	if signatureGen != signatureIn {
		fmt.Printf("signatureGen != signatureIn signatureGen=%s,signatureIn=%s\n", signatureGen, signatureIn)
		c.Ctx.WriteString("")
	} else {
		//如果请求来自于微信，则原样返回echostr参数内容 以上完成后，接入验证就会生效，开发者配置提交就会成功。
		fmt.Println("echostr:", echo)
		c.Ctx.WriteString(echo)
	}
}

func (c *WxConnectController) CreateWxMenu() {
	err := service.CreateWxMenu()
	if err != nil {
		logs.Warn("err:", err.Error())
	}
	return

}
func SaveOpenId(OpenId string) {
	var wxuser models.WxUserInfo
	Token, err := service.GetAndUpdateDBWxAToken()
	if err != nil {
		logs.Error("err", err.Error())
	}
	wxuser.AccessToken = Token
	wxuser.Openid = OpenId
	logs.Info("触发保存")
	logs.Info("Token:", wxuser.AccessToken)
	service.FetchWxInfoAndIcon(&wxuser)
}

//微信菜单用户点击 扫码响应
func (c *WxConnectController) Post() {
	c.EnableRender = false
	wxEvent := new(models.WxMenuEvent)
	bytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
	if err != nil {
		logs.Warn("微信菜单用户点击、扫码响应错误", err)
		return
	}
	err = xml.Unmarshal(bytes, wxEvent) //解析xml
	if err != nil {
		logs.Warn("微信菜单用户点击、扫码解析body错误", err)
		return
	}
	logs.Info("用户点击触发")
	SaveOpenId(wxEvent.FromUserName)
	logs.Info("CreateTime", wxEvent.CreateTime)
	logs.Info("MsgType", wxEvent.MsgType)
	logs.Info("Event", wxEvent.Event)
	logs.Info("EventKey", wxEvent.EventKey)
	logs.Info("Content", wxEvent.Content)
	var ArticlesReply models.ArticlesReply //图文消息
	var Content string                     //发送消息
	var TextReply models.TextReply         //自动回复文字

	switch wxEvent.MsgType {
	case "text":
		{
			switch {
			//自动回复
			case strings.Contains(wxEvent.Content, "原因"):
				Content = "您被驳回的原因需要具体问下您的包户干部呢~~"
			case strings.Contains(wxEvent.Content, "清理"):
				Content = `您好，如需清理个人基础信息，请在进入平安回家后右下角基本信息模块` +
					`点击“修改个人资料”可重新上传个人的基本信息。` + "\n" +
					`如需清理居住地址，车牌号，仅支持在驳回状态下电子卡列表点击被驳回的电子卡进入修改提交。`
			case strings.Contains(wxEvent.Content, "已有"):
				Content = `您好，如申请过程中提示您已有本小区电子卡，请先确认您的电子卡是否被驳回，` + "\n" +
					`如被驳回，您可在电子卡列表中找到您这张电子卡，点击进入修改。`
			case strings.Contains(wxEvent.Content, "审核"):
				Content = `您好，审核权限在您所在社区，请您耐心等待。`
			case strings.Contains(wxEvent.Content, "修改"):
				Content = `您好，在您的基本信息下方有个修改个人资料  点击您可以自行修改个人的基本信息了。` + "\n" +
					`如需修改居住地址，车牌号，仅支持驳回状态的电子卡列表点击被驳回的电子卡进入修改提交。`
			case strings.Contains(wxEvent.Content, "填错"):
				Content = `您好，在您的基本信息下方有个修改个人资料  点击您可以自行修改个人的基本信息了。` + "\n" +
					`如需修改居住地址，车牌号，仅支持驳回状态的电子卡列表点击被驳回的电子卡进入修改提交。`
			case strings.Contains(wxEvent.Content, "重置"):
				Content = `您好，如需重置个人基础信息，请在进入平安回家后右下角基本信息模块点击“修改个人资料”可重新重置个人的基本信息。` + "\n" +
					`如需重置居住地址，车牌号，仅支持在驳回状态下电子卡列表点击被驳回的电子卡进入修改提交。`
			case strings.Contains(wxEvent.Content, "清除"):
				Content = `您好，如需清除个人基础信息，请在进入平安回家后右下角基本信息模块点击“修改个人资料”可重新上传个人的基本信息。` + "\n" +
					`如需修改居住地址，车牌号，仅支持在驳回状态下电子卡列表点击被驳回的电子卡进入修改提交。`
			case strings.Contains(wxEvent.Content, "驳回"):
				Content = `非常抱歉，如您需要驳回您的电子卡，请联系社区工作人员~`
			case strings.Contains(wxEvent.Content, "15981773552"): //测试
			case wxEvent.Content == "1": //电子出入证指南
				logs.Info("电子出入证指南")
				ArticlesReply.MsgType = util.CDATA("news")
				ArticlesReply.ArticleCount = 1

				Article := []*models.Article{
					{
						Title:       "平安回家居民操作指南",
						Description: "",
						PicURL:      "http://mmbiz.qpic.cn/mmbiz_jpg/owWBkBVoicu89wBLRuIWdzlDoqzq6BvHgfy95ibFjny91icYbPTEiatOpgPqpAfgBOy2kv1DvyjuXDib8HibAQAAqBXA/0?wx_fmt=jpeg",                                                       //图片链接
						URL:         "https://mp.weixin.qq.com/s?__biz=MzAxMTU0NzA5NA==&mid=100000392&idx=1&sn=ec8afe4fc04d65528bbb5e59d6cf7277&chksm=1bbe3a312cc9b3274bec5af521dc1c2c62c3f69d69381350fa5538d748e9b96c4a5fc6c92fd3#rd", //文章跳转
					},
				}

				ArticlesReply.Articles = Article
				logs.Info("Article:", ArticlesReply.Articles)
			case strings.Contains(wxEvent.Content, "帮助"):
				str := []string{
					"社区微邻里，服务零距离！感谢您的关注。\n",
					"针对【平安回家】办理请点击下方“平安回家”进行申请。\n",
					"针对【社区服务】相关问题请直接留言联系我们办理。\n",
					"有问题找微邻里，请问有什么可以帮您？您可以输入关键字进行快捷查询哦！\n",
					"回复【帮助】查看帮助信息\n",
					"回复【1】查看平安回家操作指南\n",
					"如您所在社区需要使用更多功能，请直接在下方留言。\n",
					"受理时间工作日10:00-19:30。",
				}
				Content = strings.Join(str, "")
			default:
				logs.Info("准备转发")
				var xml models.Transfer2KF
				xml.MsgType = "transfer_customer_service"
				logs.Info("wxEvent.FromUserName", wxEvent.ToUserName)
				xml.FromUserName = util.CDATA(wxEvent.ToUserName)
				logs.Info("wxEvent.ToUserName", wxEvent.FromUserName)
				xml.ToUserName = util.CDATA(wxEvent.FromUserName)
				logs.Info("wxEvent.CreateTime", wxEvent.CreateTime)
				xml.CreateTime = int64(wxEvent.CreateTime)
				logs.Info("开始转发：", xml.FromUserName)
				c.Data["xml"] = xml
				c.ServeXML()

			}
		}
	case "event":
		{
			if wxEvent.Event == "subscribe" {
				logs.Info("subscribe")
				str := []string{
					"社区微邻里，服务零距离！感谢您的关注。\n",
					"针对【平安回家】办理请点击下方“平安回家”进行申请。\n",
					"针对【社区服务】相关问题请直接留言联系我们办理。\n",
					"有问题找微邻里，请问有什么可以帮您？您可以输入关键字进行快捷查询哦！\n",
					"回复【帮助】查看帮助信息\n",
					"回复【1】查看平安回家操作指南\n",
					"如您所在社区需要使用更多功能，请直接在下方留言。\n",
					"受理时间工作日10:00-19:30。",
				}
				Content = strings.Join(str, "")
			} else {
				dealWithMenuEvent(wxEvent)
			}
		}
	default:
		{
			//客服消息转发
			logs.Info("准备转发")
			var xml models.Transfer2KF
			xml.MsgType = "transfer_customer_service"
			logs.Info("wxEvent.FromUserName", wxEvent.FromUserName)
			xml.FromUserName = util.CDATA(wxEvent.ToUserName)
			logs.Info("wxEvent.ToUserName", wxEvent.ToUserName)
			xml.ToUserName = util.CDATA(wxEvent.FromUserName)
			logs.Info("wxEvent.CreateTime", wxEvent.CreateTime)
			xml.CreateTime = int64(wxEvent.CreateTime)
			logs.Info("开始转发：", xml.FromUserName)
			c.Data["xml"] = xml
			c.ServeXML()
			return
		}
	}
	if Content != "" {
		TextReply.CreateTime = int64(wxEvent.CreateTime)
		TextReply.ToUserName = util.CDATA(wxEvent.FromUserName)
		TextReply.FromUserName = util.CDATA(wxEvent.ToUserName)
		TextReply.MsgType = util.CDATA("text")
		TextReply.Content = util.CDATA(Content)
		logs.Info("MsgType")
		c.Data["xml"] = TextReply
		c.ServeXML()
		x, _ := xml.Marshal(TextReply)
		logs.Info("string:", string(x[:]))
		return
	} else {
		ArticlesReply.CreateTime = int64(wxEvent.CreateTime)
		ArticlesReply.ToUserName = util.CDATA(wxEvent.FromUserName)
		ArticlesReply.FromUserName = util.CDATA(wxEvent.ToUserName)
		x, _ := xml.Marshal(ArticlesReply)
		logs.Info("string:", string(x[:]))
		c.Data["xml"] = ArticlesReply
		c.ServeXML()
		return
	}

}

func dealWithMenuEvent(wxEvent *models.WxMenuEvent) {
	var wxuser models.WxUserInfo
	logs.Info("Event:", wxEvent.Event)
	switch wxEvent.Event {
	case "miniprogram":
		logs.Info("miniprogram")
		Token, err := service.GetAndUpdateDBWxAToken()
		if err != nil {
			logs.Error("err", err.Error())
		}
		wxuser.AccessToken = Token
		wxuser.Openid = wxEvent.FromUserName
		_, _ = service.FetchWxInfoAndIcon(&wxuser)
	case "view_miniprogram": //说明是点击小程序触发
		logs.Info("view_miniprogram")
		Token, err := service.GetAndUpdateDBWxAToken()
		if err != nil {
			logs.Error("err", err.Error())
		}
		wxuser.AccessToken = Token
		wxuser.Openid = wxEvent.FromUserName
		_, _ = service.FetchWxInfoAndIcon(&wxuser)

	}
}
func makeSignature(timestamp, nonce string) string {

	//1. 将 plat_token、timestamp、nonce三个参数进行字典序排序
	sl := []string{Token, timestamp, nonce}
	sort.Strings(sl)
	//2. 将三个参数字符串拼接成一个字符串进行sha1加密
	s := sha1.New()
	io.WriteString(s, strings.Join(sl, ""))

	return fmt.Sprintf("%x", s.Sum(nil))
}
